#include "minuteurdialog.h"
#include "ui_minuteurdialog.h"

#include <QPainter>
#include <QApplication>
#include <QImage>
#include <QDebug>

//----------------------------------------------
MinuteurDialog::MinuteurDialog (QWidget *parent)
    : QDialog (parent), ui (new Ui::MinuteurDialog)
{
    ui->setupUi (this);

    // "settings" = enregistrement de la configuration
    m_settings = new Settings (QApplication::organizationName (),
                             QApplication::applicationName (),
                             this);

    // configurer le dialogue
    configureDialog ();

    // initialiser l'objet QSystemTrayIcon et son menu
    m_systemTrayIcon = new QSystemTrayIcon (m_settings->appIcon (), this);
    m_systemTrayIcon->setVisible (true);
    m_systemTrayIcon->show ();
    displayStandardIcon ();

    // icône de l'application
    // qui apparaitra dans la barre des tâches
    QApplication::setWindowIcon (m_settings->appIcon ());

    installMenu ();

    // initialiser le timer
    m_timer = new QTimer (this);

    // connecter les SIGNALs et les SLOTs
    connect (ui->demarrer,	// clic surle bouton Démarrer
             SIGNAL (clicked ()),
             this,
             SLOT (onDemarrerClicked ()));

    connect (m_menu,
             SIGNAL (triggered (QAction*)),	// clic sur une entrée du menu
             this,
             SLOT (onActionTriggered (QAction*)));

    connect (m_systemTrayIcon,
             SIGNAL (activated (QSystemTrayIcon::ActivationReason)),	// quand la trayIcon est activée
             this,
             SLOT (onSystemTrayIconActivated (QSystemTrayIcon::ActivationReason)));

    connect (m_timer,
             SIGNAL (timeout ()),	// un 'top' du timer (toutes les secondes)
             this,
             SLOT (onTimerTimeOut ()));

    // Préférences
    connect (ui->isBlinking,
             SIGNAL (toggled (bool)),	// clic sur "clignotement" dans les options
             m_settings,
             SLOT (setBlinking (bool)));

    connect (ui->messageDuration,
             SIGNAL (valueChanged (int)),
             m_settings,
             SLOT (setMessageDuration (int)));

    // ... et faire démarrer le timer
    m_timer->start (1000);

    QTextEdit* te = new QTextEdit;
    ui->tabWidget->addTab(te, "title");
}
//-------------------------------------
void MinuteurDialog::configureDialog ()
{
    // s'ouvre sur le premier onglet
    ui->tabWidget->setCurrentIndex (0);

    // titre du dialogue
    setWindowTitle (m_settings->appTitle ());

//    ui->tabWidget->setTabIcon (0, QIcon::fromTheme ("start-here"));
    ui->tabWidget->setTabIcon (0, m_settings->appIcon ());
    ui->tabWidget->setTabIcon (1, QIcon::fromTheme ("preferences-desktop", QIcon(":/images/preferences-desktop.svg")));
    ui->tabWidget->setTabIcon (2, QIcon::fromTheme ("help-about", QIcon(":/images/help-about.svg")));

    // valeurs par défaut à l'ouverture
    ui->delai->setTime (QTime (0, 1, 0));			// une minute par défaut...
    ui->delai->setMinimumTime (QTime (0, 1, 0));	// ... et c'est le minimum !
    ui->message->setText (m_settings->pub ());

    // récupération des valeurs sauvegardées dans les Settings
    ui->messageDuration->setValue (m_settings->messageDuration ());
    ui->isBlinking->setChecked (m_settings->isBlinking ());

    // L'onglet "à propos" affiche le n° de version
    ui->appVersion->setText (tr ("Le Minuteur, version %1").arg (qApp->applicationVersion ()));

    // attribuer une icône au bouton démarrer
    ui->demarrer->setIcon (m_settings->newIcon ());
}
//--------------------------------
MinuteurDialog::~MinuteurDialog ()
// supprimer l'objet MinuteurDialog
{
    delete m_timer;
    delete m_systemTrayIcon;
    delete ui;
    delete m_settings;

    // suppression d'une liste de pointeurs :
    while (!m_alertList.isEmpty ()) delete m_alertList.takeLast ();
}
//---------------------------------
void MinuteurDialog::installMenu ()
// initialiser le menu
{
    m_menu = new QMenu (this);
    QAction* item;

    // 1- créer un menu
    // un QMenu est formé de QAction (les items) et de séparateurs
    // on va repérer l'item choisi par l'utilisateur
    // en regardant le data () (donnée arbitraire perso) qui lui est attribué

    item = m_menu->addAction (tr ("&Nouvelle alerte..."));
    item->setData (0);
    item->setIcon (m_settings->newIcon ());

    m_menu->addSeparator ();

    item = m_menu->addAction (tr ("&Quitter"));
    item->setData (1);
    item->setIcon (QIcon::fromTheme ("application-exit", QIcon (":/images/application-exit.png")));

    // 2- affecter le menu au clic droit sur l'icône
    m_systemTrayIcon->setContextMenu (m_menu);
}
//------------------------------------
void MinuteurDialog::onTimerTimeOut ()
// répondre à un SIGNAL timeout du timer
{
    // préparer les info-bulles
    setToolTips ();

    // parcourir la liste des alertes
    // si elle est vide,
    //  afficher l'icône du Minuteur (il attend)
    // si elle contient au moins un élément actif,
    //  faire un affichage dynamique

    if (m_alertList.isEmpty ())
        displayStandardIcon ();
    else
    {
        if (activeAlertList ().isEmpty ())
            displayAlertIcon ();
        else
            displayAnimation ();
    }
}
//--------------------------------
void MinuteurDialog::setToolTips ()
{
    // affecter les infobulles
    if (m_alertList.isEmpty ())
    {
        m_systemTrayIcon->setToolTip (m_settings->standardToolTip ());
    }
    else
    {
        QString toolTip (m_settings->tooltipsTitle ());
        foreach (Alert* alert, m_alertList)
        {
            toolTip += "\n" + alert->toolTip ();
        }
        m_systemTrayIcon->setToolTip (toolTip);
    }
}
//---------------------------------------------
QList<Alert*> MinuteurDialog::activeAlertList ()
// retourne la liste des alertes actives
{
    QList<Alert*> result;

    foreach (Alert* alert, m_alertList)
    {
        if (alert->isActive ()) result << alert;
    }

    return result;
}
//-----------------------------------------
void MinuteurDialog::displayStandardIcon ()
// afficher l'icône "attente" dans la zone de notification
{
    // affichage non animé
    m_systemTrayIcon->setIcon (m_settings->appIcon ());
}
//--------------------------------------
void MinuteurDialog::displayAlertIcon ()
// afficher l'icône "attente" dans la zone de notification
{
    // affichage non animé
    m_systemTrayIcon->setIcon (m_settings->alertIcon ());
}
//-------------------------------------
void MinuteurDialog::displayAnimation ()
// afficher une animation dans la zone de notification
{
    // dans cette version de LeMinuteur on n'affiche une
    // animation que pour la *première* alerte (first)
    Alert* alert = activeAlertList ().first ();

    // traiter l'événement alert
    if (alert->timeIsUp ())
    {
        // quand le compte à rebours est terminé,
        // afficher la notification.
        m_systemTrayIcon->showMessage (m_settings->messageTitle (),
                                     alert->message (),
                                     QSystemTrayIcon::Information,
                                     m_settings->messageDuration () * 1000); // en ms !
        // et désactiver l'événement
        alert->setInactive ();
    }
    else
    {
        qreal totalTime = alert->totalTime ();
        qreal secondsElapsed = alert->secondsElapsed ();

        // 1- demander au système la largeur et la hauteur
        // du rectangle réservé à l'icône
        // prendre la plus petite valeur des deux
        // de façon à obtenir un carré
        int width = qMin (m_systemTrayIcon->geometry ().width (),
                         m_systemTrayIcon->geometry ().height ());
        width = qMax (50, width);
        int height = width;
//        qDebug () << height << width;

//		int width = m_systemTrayIcon->geometry ().width ();
//		int height = m_systemTrayIcon->geometry ().height ();

        QRect iconRect (0, 0, width, height);

        // 2- créer une image de la taille correspondante
        QPixmap pixmap (width, height);

        // 3- initialiser l'image :
        // la remplir d'un fond transparent
        pixmap.fill (Qt::transparent);

        // 4- créer un QPainter qui va dessiner dans l'image
        QPainter trayPainter (&pixmap);
        trayPainter.setRenderHints (QPainter::Antialiasing |
                                    QPainter::TextAntialiasing,
                                    true);


        // 5- dessiner un cercle jaune sans bord
        trayPainter.setPen (Qt::NoPen);
        trayPainter.setBrush (m_settings->systrayBackgroundColor ());
        trayPainter.drawEllipse (iconRect);

        // 6- dessiner un secteur vert
        // symbolisant le délai écoulé
        int startAngle = 90; // le secteur démarre à midi (+ 90°)
        int spanAngle = - (360 * secondsElapsed / totalTime);	// et tourne dans le sens horaire (signe -)

        // en plus startAngle et spanAngle doivent être exprimés en 1/16è de degré (!!) donc :
        startAngle *= 16;
        spanAngle *= 16;

        trayPainter.setBrush (m_settings->systrayProgressColor ());
        trayPainter.setPen (Qt::NoPen);
        trayPainter.drawPie (iconRect,
                             startAngle,
                             spanAngle);

        // 7- afficher 1 fois sur deux la lettre "M"
        // (M pour Magnum ? Minuteur ? Mandriva ?)
        static bool blink = true;

        if (blink)
        {
            QFont font;
            font.setStyleHint (QFont::SansSerif, QFont::PreferAntialias);

            font.setPixelSize (2 * height / 3);	// 2/3 de la hauteur
            font.setBold (true);	// caractère gras

            trayPainter.setFont (font);
            trayPainter.setPen (m_settings->systrayFontColor ());
            trayPainter.drawText (iconRect,
                                 Qt::AlignCenter,
                                 "M");
        }

        if (m_settings->isBlinking ())
            blink = !blink;
        else
            blink = true;

        // 8- afficher le pixmap en tant qu'icône
        // dans la ZDN
        m_systemTrayIcon->setIcon (QIcon (pixmap));
        setToolTips ();
    }
}
//---------------------------------------------------------------------------------------
void MinuteurDialog::onSystemTrayIconActivated (QSystemTrayIcon::ActivationReason reason)
{
    switch (reason)
    {
    case QSystemTrayIcon::DoubleClick:
        // The system tray entry was double clicked
    case QSystemTrayIcon::Trigger:
        // The system tray entry was clicked
        if (activeAlertList ().isEmpty ()) show ();
        break;
    case QSystemTrayIcon::Unknown:
        // Unknown reason
    case QSystemTrayIcon::Context:
        // The context menu for the system tray entry was requested
    case QSystemTrayIcon::MiddleClick:
        // The system tray entry was clicked with the middle mouse button
        break;
    }
}
//------------------------------------------------------
void MinuteurDialog::onActionTriggered (QAction* action)
// gérer l'item de menu activé
// en fonction de son "indice"
{
    switch (action->data ().toInt ())
    {
        case 0:
        // désactiver tous les événements
        // (** dans cette version uniquement **)
        foreach (Alert* alert, m_alertList)
            alert->setInactive ();

        // afficher le dialogue
        show ();
        break;

        case 1:
        QApplication::quit ();
        break;
    }
}
//---------------------------------------
void MinuteurDialog::onDemarrerClicked ()
// lire les infos dans la boîte de dialogue
{
    int hours = ui->delai->time ().hour ();
    int minutes = ui->delai->time ().minute ();
    int seconds = ui->delai->time ().second ();

    QString message = ui->message->text ();

    // créer le Alert ()
    Alert* alert = new Alert (hours, minutes, seconds, message);

    // l'enregistrer dans la liste
    m_alertList << alert;

    // cacher le dialogue
    hide ();
}
